#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<winsock2.h>
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:this is a exe for onlineDisk
*********************************/
class ClientTcpIp{
private:
	WSADATA wsa;//apply for api
	SOCKET sock;//myself
	SOCKADDR_IN addrC;//server information
	char ip[20];//server Ip
	char sen[200];//what you send
	char rec[200];//what you get
	char* hostip;//host ip
	char* hostname;//host name
public:
	ClientTcpIp(const char* ps,int port=5200)
	{
		if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
			exit(0);
		memset(ip,0,20);
		strcpy(ip,ps);
		sock=socket(AF_INET,SOCK_STREAM,0);
		addrC.sin_addr.S_un.S_addr=inet_addr(ip);
		addrC.sin_family=AF_INET;
		addrC.sin_port=htons(port);
		hostip=(char*)malloc(sizeof(char)*20);
		memset(hostip,0,sizeof(char)*20);
		hostname=(char*)malloc(sizeof(char)*30);
		memset(hostname,0,sizeof(char)*30);
	}
	~ClientTcpIp()
	{
		free(hostip);
		free(hostname);
		closesocket(sock);
		WSACleanup();
	}
	bool tryConnect()
	{
		if(connect(sock,(SOCKADDR*)&addrC,sizeof(sockaddr))==SOCKET_ERROR)
			return false;
		return true;
	}
	int receiveMystl(void* prec,int len)
	{
		return recv(sock,(char*)prec,len,0);
	}
	bool sendHostMystl(const void* ps,int len)
	{
		if(send(sock,(char*)ps,len,0)==SOCKET_ERROR)
			return false;
		return true;
	}
	bool updateSocket()
	{
		closesocket(sock);
		sock=socket(AF_INET,SOCK_STREAM,0);
		if((int)sock==SOCKET_ERROR)
			return false;
		return true;
	}
	char* getHustIp()
	{
		char name[30]={0};
		gethostname(name,30);
		hostent* phost=gethostbyname(name);
		in_addr addr;
		char* p=phost->h_addr_list[0];
		memcpy(&addr.S_un.S_addr,p,phost->h_length);
		memset(hostip,0,sizeof(char)*20);
		memcpy(hostip,inet_ntoa(addr),strlen(inet_ntoa(addr)));
		return hostip;
	}
	char* getHostName()
	{
		char name[30]={0};
		gethostname(name,30);
		memcpy(hostname,name,30);
		return hostname;
	}
};
struct Msg{
	int flag;
	int len;
	char name[100];
};
enum Model{
	REC=0,SEN=1
};
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:read form file to judge if is first load
*********************************/
char* readFile(char* ip)
{
	FILE* fp=fopen("ip.txt","rb+");
	if(fp==NULL)//show is first to load in
		return NULL;
	else
		if(fscanf(fp,"%s",ip)<=0)
		{
			fclose(fp);
			return NULL;
		}
		else
		{
			fclose(fp);
			return ip;
		}
	fclose(fp);
	return ip;
}
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:write the ip to file
*********************************/
bool writeFile(const char* ip)
{
	FILE* fp=fopen("ip.txt","wb+");
	if(fp==NULL)
		return false;
	fprintf(fp,"%s",ip);
	fclose(fp);
	return true;
}
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:show menu of choices
*********************************/
Model showMenu()
{
	int temp=0;
	printf("please choose send(1) or get(0):");
	while(scanf("%d",&temp)<=0||(temp!=0&&temp!=1))
	{
		fflush(stdin);
		printf("wrong please input again:");
	}
	if(temp==1)
		return SEN;
	else
		return REC;
}
/********************************
	author:chenxuan
	date:2021/8/15
	funtion:get file message
*********************************/
bool getFileMsg(const char* fileName,char* buffer,int* pfileLen)
{
	int i=0;
	FILE* fp=fopen(fileName,"rb+");
	if(fp==NULL)
		return false;
	fseek(fp,0,SEEK_END);
	*pfileLen=ftell(fp);
	fseek(fp,0,SEEK_SET);
	for(i=0;i<*pfileLen;i++)
		buffer[i]=fgetc(fp);
	buffer[i+1]=0;
	fclose(fp);
	return true;
}
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:send files to server
*********************************/
bool sendFile(ClientTcpIp& client)
{
	char name[256]={0},*buffer=NULL,*temp=NULL;
	int mallocLen=0,len=0;
	Msg msg={0};
	while(strcmp(name,"quit")!=0)
	{
		fflush(stdin);
		printf("please input the name of file:");
		scanf("%s",name);
		FILE* fp=fopen(name,"rb+");
		if(fp==NULL)
			continue;
		fseek(fp,0,SEEK_END);
		len=ftell(fp);
		fclose(fp);
		if(len+1>mallocLen)
		{
			if(buffer!=NULL)
				free(buffer);
			buffer=(char*)malloc(sizeof(char)*len+10);
			mallocLen=len+10;
		}
		memset(buffer,0,sizeof(char)*(len+1));
		if(false==getFileMsg(name,buffer,&len))
			continue;
		
		msg.len=len;
		msg.flag=1;
		if((temp=strrchr(name,'\\'))==NULL)
			strcpy(msg.name,name);
		else
			strcpy(msg.name,temp+1);
		if(false==client.sendHostMystl(&msg,sizeof(Msg)))
			printf("send first wrong\n");
		if(false==client.sendHostMystl(buffer,len))
			printf("send two wrong\n");
		printf("waiting %d \n",msg.len/112600);
		Sleep((int)(msg.len/112));
	}
	if(buffer!=NULL)
		free(buffer);
	return true;
}
/********************************
	author:chenxuan
	date:2021/8/16
	funtion:recv the file message
*********************************/
void recvFile(ClientTcpIp& client)
{
	char name[100]={0},*pfile=NULL;
	Msg msg={0};
	int len=0,all=0;
	while(strcmp(name,"quit")!=0)
	{
		all=0;len=0;
		fflush(stdin);
		printf("plaese input the name of get file:");
		scanf("%s",name);
		strcpy(msg.name,name);
		msg.flag=2;
		if(false==client.sendHostMystl(&msg,sizeof(Msg)))
			printf("send first wrong\n");
		if(-1==client.receiveMystl(&msg,sizeof(Msg)))
			printf("get first wrong\n");
		if(msg.flag!=2)
			continue;
		FILE* fp=fopen(msg.name,"wb+");
		if(NULL==fp)
			continue;
		if(pfile!=NULL)
			free(pfile);
		pfile=(char*)malloc(sizeof(char)*msg.len+10);
		if(pfile==NULL)
			continue;
		memset(pfile,0,sizeof(char)*msg.len+10);
		while(msg.len-all>5)
		{
			len=client.receiveMystl(pfile+all,msg.len+1);
			if(len>0)
				all+=len;
			printf("len:%d get:%d\n",msg.len,all);
		}
		for(int i=0;i<msg.len;i++)
			fputc(pfile[i],fp);
		fclose(fp);
		printf("get %s success\n",msg.name);
	}
	if(pfile!=NULL)
		free(pfile);
}
/********************************
	author:chenxuan
	date:2021/8/16
	funtion:show file to download
*********************************/
void getFileList(ClientTcpIp& client)
{
	Msg msg={0};
	char* ptemp=NULL;
	msg.flag=0;
	if(false==client.sendHostMystl(&msg,sizeof(Msg)))
		return;
	if(false==client.receiveMystl(&msg,sizeof(Msg)))
		return;
	ptemp=(char*)malloc(sizeof(char)*(msg.len+10));
	if(NULL==ptemp)
		return;
	memset(ptemp,0,sizeof(char)*(msg.len+10));
	if(false==client.receiveMystl(ptemp,msg.len))
		return;
	printf("\nfile List:\n%s\n",ptemp);
	free(ptemp);
	return;
}
/********************************
	author:chenxuan
	date:2021/8/13
	funtion:the main funtion
*********************************/
void test()
{
	char ip[100]={0};
	system("title welcome to online disk system");
	if(NULL==readFile(ip))
	{
		printf("please input the remote disk ip:");
		while(scanf("%s",ip)<=0)
			printf("ip wrong please input again:");
		if(false==writeFile(ip))
		{
			fflush(stdin);
			printf("write wrong\n");
			getchar();
			return;
		}
	}
	ClientTcpIp client(ip,5209);
	if(false==client.tryConnect())
	{
		fflush(stdin);
		printf("connect wrong\n");
		getchar();
		return;
	}
	printf("connect %s ok\n",ip);
	while(1)
		switch (showMenu()) 
		{
			case REC:
				getFileList(client);
				recvFile(client);
				break;
			case SEN:
				sendFile(client);
				break;
			default:
				break;
		}
}
int main()
{
	test();
}
